/**
 * @Title: StudentServiceImpl.java
 * @Description:
 * @author zsw
 * <p>
 * Copyright(C) 2018-2019    NPlus
 * Company:   无锡核心信息科技有限公司
 * @version V2.0.0
 * @Date: 16:39 2019/10/15
 * <p>
 * 修改历史:
 * Date                 Author        Version        Description
 * -----------------------------------------------------------------------------------
 * 16:39 2019/10/15       zsw        2.0.0           初始化版本
 */
package com.example.springjpa.service.impl;

import com.example.springjpa.dao.StudentDao;
import com.example.springjpa.model.Student;
import com.example.springjpa.service.StudentService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.PropertyDescriptor;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;


@Service
@Transactional
//@CacheConfig(cacheNames = "user") // 如果使用该注解, 方法中则可以省略 cacheNames 配置
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentDao studentDao;

    @Autowired
    private StringRedisTemplate redisTemplate;
    //插入一个学生
    @Override
    public void addStudent(Student student) {
        studentDao.save(student);
    }

    @Override
    public Collection<Student> findAll() {
        Collection<Student> students =studentDao.findAll();
        return students;
    }

    @Override
    // 缓存的最终 key 值为 user::id
    @Cacheable(cacheNames = "student", key = "#id")
    public Student findOneStudent(Long id) {
        return studentDao.getOne(id);
        }

    @Override
    // condition: 执行方法前判断是否使用注解的功能; unless: 执行方法后，判断是否使用注解提供的功能
  @CachePut(cacheNames = "student", key = "#student.id", condition = "#student.id>10", unless = "#result.flag = false ")
   // @CachePut(value = "student", key = "#student.getId()")
    public Student putStudent(Student student) {
        Student student1 = studentDao.getOne(student.getId());
        BeanUtils.copyProperties(student1,student,getNoNullProperties(student));
        studentDao.save(student);
        return student;
    }

    @Override
    // 默认规则: 只有一个参数则 key 值取该参数, 如果有多个参数则将这些参数拼接起来作为 key
    @CacheEvict(cacheNames = "student")
    public void delStudent(Long id) {
        studentDao.deleteById(id);
    }

    // allEntries 清除 cacheNames 下所有 key; beforeInvocation 方法执行前清除
    @CacheEvict(cacheNames = "student", allEntries = true, beforeInvocation = true)
    public void deleteAll() {
        studentDao.deleteAll();
    }

    private static String[] getNoNullProperties(Object target) {
        BeanWrapper srcBean = new BeanWrapperImpl(target);
        PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
        Set<String> noEmptyName = new HashSet<>();
        for (PropertyDescriptor p : pds) {
            Object value = srcBean.getPropertyValue(p.getName());
            if (value != null) noEmptyName.add(p.getName());
        }
        String[] result = new String[noEmptyName.size()];
        return noEmptyName.toArray(result);
    }
}
